home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / elv18src.zip / move2.c < prev    next >
C/C++ Source or Header  |  1994-01-02  |  6KB  |  312 lines

  1. /* move2.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This function contains the movement functions that perform RE searching */
  12.  
  13. #include "config.h"
  14. #include "vi.h"
  15. #include "regexp.h"
  16.  
  17.  
  18. static regexp    *re;    /* compiled version of the pattern to search for */
  19. static        prevsf;    /* boolean: previous search direction was forward? */
  20.  
  21. #ifndef NO_EXTENSIONS
  22. /*ARGSUSED*/
  23. MARK m_wsrch(word, m, cnt)
  24.     char    *word;    /* the word to search for */
  25.     MARK    m;    /* the starting point */
  26.     int    cnt;    /* ignored */
  27. {
  28.     char    buffer[30];
  29.  
  30.     /* wrap \< and \> around the word */
  31.     strcpy(buffer, "/\\<");
  32.     strcat(buffer, word);
  33.     strcat(buffer, "\\>");
  34.  
  35.     /* show the searched-for word on the bottom line */
  36.     move(LINES - 1, 0);
  37.     qaddstr(buffer);
  38.     clrtoeol();
  39.     refresh();
  40.  
  41.     /* search for the word */
  42.     return m_fsrch(m, buffer);
  43. }
  44. #endif
  45.  
  46. MARK    m_nsrch(m, cnt, cmd)
  47.     MARK    m;    /* where to start searching */
  48.     long    cnt;    /* number of searches to do */
  49.     int    cmd;    /* command character -- 'n' or 'N' */
  50. {
  51.     int    oldprevsf; /* original value of prevsf, so we can fix any changes */
  52.  
  53.     DEFAULT(1L);
  54.  
  55.     /* clear the bottom line.  In particular, we want to loose any
  56.      * "(wrapped)" notice.
  57.      */
  58.     move(LINES - 1, 0);
  59.     clrtoeol();
  60.  
  61.     /* if 'N' command, then invert the "prevsf" variable */
  62.     oldprevsf = prevsf;
  63.     if (cmd == 'N')
  64.     {
  65.         prevsf = !prevsf;
  66.     }
  67.  
  68.     /* search forward if prevsf -- i.e., if previous search was forward */
  69.     while (--cnt >= 0L && m != MARK_UNSET)
  70.     {
  71.         if (prevsf)
  72.         {
  73.             m = m_fsrch(m, (char *)0);
  74.         }
  75.         else
  76.         {
  77.             m = m_bsrch(m, (char *)0);
  78.         }
  79.     }
  80.  
  81.     /* restore the old value of prevsf -- if cmd=='N' then it was inverted,
  82.      * and the m_fsrch() and m_bsrch() functions force it to a (possibly
  83.      * incorrect) value.  The value of prevsf isn't supposed to be changed
  84.      * at all here!
  85.      */
  86.     prevsf = oldprevsf;
  87.     return m;
  88. }
  89.  
  90.  
  91. MARK    m_fsrch(m, ptrn)
  92.     MARK    m;    /* where to start searching */
  93.     char    *ptrn;    /* pattern to search for */
  94. {
  95.     long    l;    /* line# of line to be searched */
  96.     char    *line;    /* text of line to be searched */
  97.     int    wrapped;/* boolean: has our search wrapped yet? */
  98.     int    pos;    /* where we are in the line */
  99. #ifndef CRUNCH
  100.     long    delta = INFINITY;/* line offset, for things like "/foo/+1" */
  101. #endif
  102.  
  103.     /* remember: "previous search was forward" */
  104.     prevsf = TRUE;
  105.  
  106.     if (ptrn && *ptrn)
  107.     {
  108.         /* locate the closing '/', if any */
  109.         line = parseptrn(ptrn);
  110. #ifndef CRUNCH
  111.         if (*line)
  112.         {
  113.             delta = atol(line);
  114.         }
  115. #endif
  116.         ptrn++;
  117.  
  118.         /* free the previous pattern */
  119.         if (re) _free_(re);
  120.  
  121.         /* compile the pattern */
  122.         re = regcomp(ptrn);
  123.         if (!re)
  124.         {
  125.             return MARK_UNSET;
  126.         }
  127.     }
  128.     else if (!re)
  129.     {
  130.         msg("No previous expression");
  131.         return MARK_UNSET;
  132.     }
  133.  
  134.     /* search forward for the pattern */
  135.     pos = markidx(m) + 1;
  136.     pfetch(markline(m));
  137.     if (pos >= plen)
  138.     {
  139.         pos = 0;
  140.         m = (m | (BLKSIZE - 1)) + 1;
  141.     }
  142.     wrapped = FALSE;
  143.     for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
  144.     {
  145.         /* wrap search */
  146.         if (l > nlines)
  147.         {
  148.             /* if we wrapped once already, then the search failed */
  149.             if (wrapped)
  150.             {
  151.                 break;
  152.             }
  153.  
  154.             /* else maybe we should wrap now? */
  155.             if (*o_wrapscan)
  156.             {
  157.                 l = 0;
  158.                 wrapped = TRUE;
  159.                 continue;
  160.             }
  161.             else
  162.             {
  163.                 break;
  164.             }
  165.         }
  166.  
  167.         /* get this line */
  168.         line = fetchline(l);
  169.  
  170.         /* check this line */
  171.         if (regexec(re, &line[pos], (pos == 0)))
  172.         {
  173.             /* match! */
  174.             if (wrapped && *o_warn)
  175.                 msg("(wrapped)");
  176. #ifndef CRUNCH
  177.             if (delta != INFINITY)
  178.             {
  179.                 l += delta;
  180.                 if (l < 1 || l > nlines)
  181.                 {
  182.                     msg("search offset too big");
  183.                     return MARK_UNSET;
  184.                 }
  185.                 force_flags = LNMD|INCL;
  186.                 return MARK_AT_LINE(l);
  187.             }
  188. #endif
  189.             return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
  190.         }
  191.         pos = 0;
  192.     }
  193.  
  194.     /* not found */
  195. #ifdef DEBUG
  196.     msg("/%s/ not found", ptrn);
  197. #else
  198.     msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
  199. #endif
  200.     return MARK_UNSET;
  201. }
  202.  
  203. MARK    m_bsrch(m, ptrn)
  204.     MARK    m;    /* where to start searching */
  205.     char    *ptrn;    /* pattern to search for */
  206. {
  207.     long    l;    /* line# of line to be searched */
  208.     char    *line;    /* text of line to be searched */
  209.     int    wrapped;/* boolean: has our search wrapped yet? */
  210.     int    pos;    /* last acceptable idx for a match on this line */
  211.     int    last;    /* remembered idx of the last acceptable match on this line */
  212.     int    try;    /* an idx at which we strat searching for another match */
  213. #ifndef CRUNCH
  214.     long    delta = INFINITY;/* line offset, for things like "/foo/+1" */
  215. #endif
  216.  
  217.     /* remember: "previous search was not forward" */
  218.     prevsf = FALSE;
  219.  
  220.     if (ptrn && *ptrn)
  221.     {
  222.         /* locate the closing '?', if any */
  223.         line = parseptrn(ptrn);
  224. #ifndef CRUNCH
  225.         if (*line)
  226.         {
  227.             delta = atol(line);
  228.         }
  229. #endif
  230.         ptrn++;
  231.  
  232.         /* free the previous pattern, if any */
  233.         if (re) _free_(re);
  234.  
  235.         /* compile the pattern */
  236.         re = regcomp(ptrn);
  237.         if (!re)
  238.         {
  239.             return MARK_UNSET;
  240.         }
  241.     }
  242.     else if (!re)
  243.     {
  244.         msg("No previous expression");
  245.         return MARK_UNSET;
  246.     }
  247.  
  248.     /* search backward for the pattern */
  249.     pos = markidx(m);
  250.     wrapped = FALSE;
  251.     for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
  252.     {
  253.         /* wrap search */
  254.         if (l < 1)
  255.         {
  256.             if (*o_wrapscan)
  257.             {
  258.                 l = nlines + 1;
  259.                 wrapped = TRUE;
  260.                 continue;
  261.             }
  262.             else
  263.             {
  264.                 break;
  265.             }
  266.         }
  267.  
  268.         /* get this line */
  269.         line = fetchline(l);
  270.  
  271.         /* check this line */
  272.         if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
  273.         {
  274.             /* match!  now find the last acceptable one in this line */
  275.             do
  276.             {
  277.                 last = (int)(re->startp[0] - line);
  278.                 try = (int)(re->endp[0] - line);
  279.             } while (try > 0
  280.                  && regexec(re, &line[try], FALSE)
  281.                  && (int)(re->startp[0] - line) < pos);
  282.  
  283.             if (wrapped && *o_warn)
  284.                 msg("(wrapped)");
  285. #ifndef CRUNCH
  286.             if (delta != INFINITY)
  287.             {
  288.                 l += delta;
  289.                 if (l < 1 || l > nlines)
  290.                 {
  291.                     msg("search offset too big");
  292.                     return MARK_UNSET;
  293.                 }
  294.                 force_flags = LNMD|INCL;
  295.                 return MARK_AT_LINE(l);
  296.             }
  297. #endif
  298.             return MARK_AT_LINE(l) + last;
  299.         }
  300.         pos = BLKSIZE;
  301.     }
  302.  
  303.     /* not found */
  304. #ifdef DEBUG
  305.     msg("?%s? not found", ptrn);
  306. #else
  307.     msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
  308. #endif
  309.     return MARK_UNSET;
  310. }
  311.  
  312.